/*********************************************************************************
 *      Copyright:  (C) 2025 iot25<lingyun@email.com>
 *                  All rights reserved.
 *
 *       Filename:  pack_data.c
 *    Description:  This file 
 *                 
 *        Version:  1.0.0(03/05/25)
 *         Author:  iot25 <lingyun@email.com>
 *      ChangeLog:  1, Release initial version on "03/05/25 21:30:29"
 *                 
 ********************************************************************************/
#include<stdio.h>
#include<string.h>
#include<stdint.h>

#include "pack_data.h"
#include "logger.h"

//crc16校验函数
uint8_t crc16(const uint8_t *data, size_t length)
{
    uint16_t        crc = 0xFFFF;
	size_t			i;
	int				j;
    for (i = 0; i < length; i++)
	{
		//处理的是一个一个字节
        crc ^= (uint16_t)data[i] << 8; //将当前字节移入高8位
        for (j = 0; j < 8; j++)
		{
			//逐个处理一个字节的8个位
            if (crc & 0x8000)
			{
				//判断最高位是不是1
                crc = (crc << 1) ^ 0x1021;
            }
			else
			{
                crc <<= 1;
            }
        }
    }
    return crc;
}
//变换字节序
uint16_t to_big_endian(uint16_t num)
{
	return (num << 8) | (num >> 8);
}

int pack_data(pack_t *pack, char *data, int bytes)
{
	int          written = 0;
	uint8_t      crc;
	if ( NULL == pack || NULL == data || bytes <= 0 )
	{
		log_error("Invalid arguments!\n");
		return -1;
	}

	memset(data, 0, bytes);
	written=snprintf(data, bytes, "id:%s|temp:%f|time:%s\n", 
			pack->dev_id, pack->temperature, pack->dev_time);
	
	if(written >= bytes)
    {
			log_debug("dev_id: %s, temperature: %f, dev_time: %s\n", 
					pack->dev_id, pack->temperature, pack->dev_time);
    		log_error("Buffer overflow: needed=%d, available=%d\n", written, bytes);
    		return -2;
	}
	// 计算 CRC
    crc = crc16((const uint8_t *)data, written);
    if (written + 6 > bytes)
	{ // crc需要增加7字节："|crc：0x"+4位16进制
        log_error("When adding CRC: needed=%d, available=%d\n", written + 6, bytes);
        return -2;
    }

    written += snprintf(data + written, bytes - written, "|crc:0x%04X", crc);
	
	log_debug("pack_data successfully！");
	return written;
}


int pack_tlv(pack_t *pack, uint8_t *tlv_data, int bytes)
{
	int				offset = 0;
	uint16_t		crc;
	uint8_t			id_length = strlen(pack->dev_id);

	if (NULL == pack || NULL == tlv_data || bytes <= 0)
	{
        log_error("Invalid arguments!\n");
        return -1;
    }

    /*+----------------------+
     *|    TLV Header(2B)    |
     *+----------------------+*/
	*(uint16_t *)tlv_data = to_big_endian(TLV_HEADER);
	offset += 2;

	/* 打包 ID 字段的 TLV 块 */
	if (offset + 3 + id_length > bytes) 
	{  // Tag(1B) + Length(2B) + Value(id_length)
    	log_error("Buffer overflow when packing ID");
    	return -2;
	}
	tlv_data[offset++] = TAG_ID;                             
	*(uint16_t *)(tlv_data + offset) = to_big_endian(id_length); 
	offset += 2;
	memcpy(tlv_data + offset, pack->dev_id, id_length);      
	offset += id_length;

	/* 打包温度字段的 TLV 块 */
	if (offset + 3 + sizeof(float) > bytes)
	{
    	log_error("Buffer overflow when packing Temperature");
    	return -2;
	}
	tlv_data[offset++] = TAG_TEMPERATURE;                     
	*(uint16_t *)(tlv_data + offset) = to_big_endian(sizeof(float)); 
	offset += 2;
	float temp_big_endian = to_big_endian(pack->temperature); 
	memcpy(tlv_data + offset, &temp_big_endian, sizeof(float)); 
	offset += sizeof(float);

	/* 打包时间字段的 TLV 块 */
	uint8_t time_length = strlen(pack->dev_time);
	if (offset + 3 + time_length > bytes) 
	{
    	log_error("Buffer overflow when packing Time");
   		 return -2;
	}
	tlv_data[offset++] = TAG_TIME;                            
	*(uint16_t *)(tlv_data + offset) = to_big_endian(time_length); 
	offset += 2;
	memcpy(tlv_data + offset, pack->dev_time, time_length);  
	offset += time_length;

	  /*+----------------------+
     *|      TLV CRC(2B)     |
     *+----------------------+*/
	/* 计算并写入 CRC */
	crc = crc16(tlv_data, offset);
	*(uint16_t *)(tlv_data + offset) = to_big_endian(crc);   // CRC（大端序）
	offset += 2;

	return offset;
}


// JSON 格式数据打包函数
int pack_data_json(pack_t *pack, char *data, int bytes)
{
	int			written;

    if (NULL == pack || NULL == data || bytes <= 0)
    {
        log_error("Invalid arguments!\n");
        return -1;
    }

    memset(data, 0, bytes);
    written = snprintf(data, bytes, "{\"devid\":\"%s\", \"temperature\":\"%.3f\",\"time\":%s}",
                           pack->dev_id, pack->temperature, pack->dev_time);

    if (written >= bytes)
    {
        log_error("Buffer overflow: needed=%d, available=%d\n", written, bytes);
        return -2;
    }

    log_debug("pack_data_json successfully\n");
    return written;
}

